package com.lightspring.context;

import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.XmlUtil;
import com.lightspring.beans.BeanFactory;
import com.lightspring.beans.BeansException;
import com.lightspring.beans.DefaultListableBeanFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import java.io.*;

/**
 * @author: 毅航
 * @create: 2023-10-14 18:09
 * @Description:
 */
public class ClassPathXmlApplicationContext implements BeanFactory {


    private String[] configLocations;
    private BeanFactory beanFactory;
    public void ClassPathXmlApplicationContext() {
    }

    /**
     * 从 XML 中加载 BeanDefinition，并刷新上下文
     *
     * @param configLocations
     * @throws BeansException
     */
    public ClassPathXmlApplicationContext(String configLocations) throws BeansException {
        this(new String[]{configLocations});
    }

    /**
     * 从 XML 中加载 BeanDefinition，并刷新上下文
     * @param configLocations
     * @throws BeansException
     */
    public ClassPathXmlApplicationContext(String[] configLocations) throws BeansException {
        // 设定加载路径
        this.configLocations = configLocations;
        // 刷新容器信息
        refresh();
    }

    /**
     * @Description: 刷新容器处理
     * @param
     * @return void
     */

    private void refresh() {

        // 构架工厂
        this.beanFactory = new DefaultListableBeanFactory();
        // 加载配置文件
        loadBeanDefinitions(beanFactory);
    }

    /**
     * @Description: 加载配置文件
     * @param beanFactory
     * @return void
     */
    private void loadBeanDefinitions(BeanFactory beanFactory) {
        for (String location : this.configLocations) {

            try (InputStream inputStream = this.getClass().getClassLoader()
                    .getResourceAsStream(location)) {
               // Document doc = XmlUtil.readXML(inputStream);
                Document doc = XmlUtil.readXML(new InputStreamReader(inputStream));
                // 获取根节点
                Element root = doc.getDocumentElement();
                // 获取父节点的孩子节点
                NodeList childNodes = root.getChildNodes();
                // 遍历 最终直解析bean标签信息
                for (int i = 0 ; i < childNodes.getLength();  i ++) {
                    // 判断元素
                    if (!(childNodes.item(i) instanceof Element)) {
                        continue;
                    }
                    // 判断对象
                    if (!"bean".equals(childNodes.item(i).getNodeName())) {
                        continue;
                    }
                    Element bean = (Element) childNodes.item(i);
                    String id = bean.getAttribute("id");
                    String name = bean.getAttribute("name");
                    String className = bean.getAttribute("class");


                    // 加载class 放置于beanDefinition

                    Class<?> beanClass = Class.forName(className);
                    // 优先级 id > name
                    String beanName = StrUtil.isNotEmpty(id) ? id : name;
                    // 如果beanName信息为空 采用类名代替
                    if (StrUtil.isEmpty(beanName)) {
                        beanName = StrUtil.lowerFirst(beanClass.getSimpleName());
                    }

                    // 将生成的bean存入到容器
                    beanFactory.registerBeanDefinition(beanName,beanClass.newInstance());
                }
            } catch (IOException e) {
                throw new BeansException("File not found or read file cause error");
            } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
                throw new BeansException("bean class path is cause error,please check classPath");
            }
        }
    }


    protected String[] getConfigLocations() {
        return configLocations;
    }

    @Override
    public Object getBean(String beanName) throws BeansException {
        return this.beanFactory.getBean(beanName);
    }

    @Override
    public void registerBeanDefinition(String beanName, Object bd) {
        throw new BeansException("No Support calling");
    }
}
